<script lang="ts">
import {defineComponent, PropType} from 'vue'
import DialogAndBlock from "../DialogAndBlock/index.vue";
import {FormConfigItem} from "../DynamicForm3/types";
import {TableConfigItem, TableEventFirstParam} from "../DynamicTable3/types";
import DynamicForm from "../DynamicForm3/index.vue";
import DynamicTable from "../DynamicTable3/index.vue";
import ListPage from "../ListPage/index.vue";
import FlexAuto3 from "../FlexAuto3.vue";
import {SearchListFunc, SearchListParams} from "../ListPage/type";
import {deepClone} from "../../utils";
import emptyImg from './img/empty'

export default defineComponent({
  name: "SelectObject3",
  components: {
    FlexAuto3,
    ListPage,
    DialogAndBlock,
    DynamicForm,
    DynamicTable,
  },
  props: {
    modelValue: {
      type: Array,
      default: ()=>[]
    },
    title: {
      type:String,
      default: '数据选择'
    },
    rowKey: {
      type: String,
      default: 'id',
    },
    rowName: {
      type: String,
      default: 'name',
    },
    resultWidth: {
      type: String,
      default: '200px',
    },
    formConfigList: {
      type:Array as PropType<FormConfigItem[]>,
      default: ()=>[]
    },
    tableConfigList: {
      type: Array as PropType<TableConfigItem[]>,
      default: ()=>[]
    },
    multipleSelect: { // 多选
      type: Boolean,
      default: true,
    },
    asyncSearchList: { // 远程请求方法
      type: Function as PropType<SearchListFunc>,
      default:(search:SearchListParams)=>Promise.resolve({
        list: [],
        total: 0,
      }),
      require: true,
    },
  },
  data() {
    return {
      asyncModelValue: [],
      searchData: {},
      filterName: '',
      confirmBeforeValue: [],
      tableList: [],
      emptyImg
    }
  },
  watch: {
    modelValue: {
      deep: true,
      immediate: true,
      handler(val) {
        this.asyncModelValue = deepClone(val)
        this.confirmBeforeValue = deepClone(val)
      }
    }
  },
  computed: {
    computedTableConfigList() {
      let result = []
      if(this.multipleSelect) {
        result.push({
          type: 'selection',
          width: '55'
        })
      } else {
        result.push({
          type: 'radio',
          width: '55',
        })
      }
      result.push(...this.tableConfigList)
      return result
    },
    resultNameFilter(){
      return this.asyncModelValue.filter(i=>{
        if(i[this.rowName].includes(this.filterName)){
          return true
        }
        return false
      })
    },
  },
  emits: [
    'confirm',
    'update:modelValue'
  ],
  methods: {
    updateAsyncModelValue(val) {
      this.asyncModelValue = val
      this.$emit('update:modelValue',val)
    },
    open() {
      this.$refs.dialogRef.open()
    },
    opened() {
      if(this.tableList.length) {
        this.tableToSelect()
      }
    },
    tableSelect({addSelect,removeSelect}: TableEventFirstParam) {
      addSelect.forEach(item => {
        let find = this.asyncModelValue.find(row => this.$refs.DynamicTableRef.rowEquals(row, item))
        if (!find) {
          this.asyncModelValue.push(item)
        }
      })
      removeSelect.forEach(item => {
        let find = this.asyncModelValue.findIndex(row => this.$refs.DynamicTableRef.rowEquals(row, item))
        if (find > -1) {
          this.asyncModelValue.splice(find, 1)
        }
      })
    },
    cancal() {
      this.$refs.dialogRef.close()
    },
    closed() {
      this.updateAsyncModelValue(deepClone(this.confirmBeforeValue))
      if(this.tableList.length) {
        this.tableToSelect()
      }
    },
    confirm() {
      this.updateAsyncModelValue(deepClone(this.asyncModelValue))
      this.$refs.dialogRef.close()
      this.$emit('confirm',this.asyncModelValue)
    },
    searchList(search) {
      return this.asyncSearchList({
        ...search,
        ...this.searchData
      }).then(res => {
        this.tableList = res.list
        this.tableToSelect()
        return res
      })
    },
    tableToSelect() {
      let list = this.tableList
      this.$nextTick(()=>{
        list.forEach(item => {
          let find = this.asyncModelValue.find(row => this.$refs.DynamicTableRef.rowEquals(row, item))
          this.$refs.DynamicTableRef.toggleRowSelection(item, !!find)
        })
      })
      return list
    },
    getTableSlot() {
      let start = 'table_'
      return Object.keys(this.$slots).filter(i=>{
        return i.startsWith(start);
      }).map(i=>{
        return {
          name: i,
          tableName: i.substring(i.indexOf(start) + start.length)
        }
      })
    },
    getFormSlot() {
      let start = 'form_'
      return Object.keys(this.$slots).filter(i=>{
        return i.startsWith(start);
      }).map(i=>{
        return {
          name: i,
          formName: i.substring(i.indexOf(start) + start.length)
        }
      })
    },
    clearAll() {
      this.asyncModelValue = []
      this.tableToSelect()
    },
    resultItemClose(item,index){
      const findIndex = this.asyncModelValue.findIndex(r=>this.$refs.DynamicTableRef.rowEquals(item,r))
      if(findIndex>-1) {
        this.asyncModelValue.splice(findIndex,1)
        this.tableToSelect()
      }
    }
  }
})
</script>

<template>
  <DialogAndBlock
    :title="title"
    ref="dialogRef"
    @closed="closed"
    @opened="opened"
  >
    <div class="selectObjectContent">
      <ListPage
        :searchList="searchList"
        ref="ListPageRef"
      >
        <template #search="{getList,resetGetList}">
          <div>
            <DynamicForm
              v-model="searchData"
              search
              :form-config-list="formConfigList"
              label-suffix="："
              :created-init-value="false"
              @search="getList"
            >
              <template
                v-for="(item,index) in getFormSlot()"
                #[item.formName]="props">
                <slot :key="item.name+index" :name="item.name" v-bind="props"></slot>
              </template>
              <el-form-item>
                <el-button type="primary" @click="getList">搜索</el-button>
                <el-button @click="resetGetList">重置</el-button>
              </el-form-item>
            </DynamicForm>
          </div>
        </template>
        <template #list="{listData,listHeight,loading}">
          <div :style="{height: listHeight +'px'}" class="tableAndResult">
            <FlexAuto3>
              <DynamicTable
                :created-init-value="false"
                :data="tableList"
                v-loading="loading"
                :height="listHeight"
                :row-key="rowKey"
                :table-config-list="computedTableConfigList"
                ref="DynamicTableRef"
                @selectChangeEvent="tableSelect"
                countAddAndRemoveUseRowKey
              >
                <template
                  v-for="(item,index) in getTableSlot()"
                  #[item.tableName]="props">
                  <slot :key="item.name+index" :name="item.name" v-bind="props"></slot>
                </template>
              </DynamicTable>
            </FlexAuto3>
            <div :style="{width: resultWidth}" class="resultList">
              <div>
                <el-tag type="info"
                        disable-transitions
                        class="resultTipWord">
                  选中的结果
                </el-tag>
                <el-input
                  v-if="multipleSelect"
                  v-model="filterName"
                  clearable
                  placeholder="过滤"
                >
                  <template #append>
                    <el-button @click="clearAll">
                      清空
                    </el-button>
                  </template>
                </el-input>
              </div>
              <FlexAuto3>
                <div class="resultDiv">
                  <div
                    v-for="(item,index) in resultNameFilter"
                    :key="'resultNameFilter'+index+item[rowKey]"
                  >
                    <el-tag type="success"
                            disable-transitions
                            @close="resultItemClose(item,index)"
                            closable>
                      {{ item[rowName] }}
                    </el-tag>
                  </div>
                </div>
                <img
                  v-if="!resultNameFilter.length"
                  :src="emptyImg"
                />
              </FlexAuto3>
            </div>
          </div>
        </template>
      </ListPage>
    </div>
    <template #footer>
      <div class="btns">
        <el-button
          @click="cancal"
        >取消
        </el-button>
        <el-button
          type="primary"
          @click="confirm"
        >确定
        </el-button>
      </div>
    </template>
  </DialogAndBlock>
</template>

<style scoped lang="scss">
.selectObjectContent{
  height: 70vh;
  overflow: hidden;
  .tableAndResult{
    display: flex;
  }
  .resultList{
    display: flex;
    flex-direction: column;
    img{
      width: 100%;
    }
    .resultDiv{
      overflow: auto;
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }
    .resultTipWord {
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 20px;
      padding: 10px;
      height: auto;
    }
  }
}
.btns{
  text-align: right;
}
</style>
